package com.charlotte.study.gupao.interpreter.calculate.v2;

import com.charlotte.study.gupao.interpreter.calculate.v1.IArithmeticInterpreter;
import com.charlotte.study.gupao.interpreter.calculate.v1.Interpreter;
import com.charlotte.study.gupao.interpreter.calculate.v1.NumberArithmeticInterpreter;

import java.util.Stack;

/**
 * @author junjie.ding
 * @date 2020/3/23
 */
public class Calculator {

    // 数字栈
    private Stack<IArithmeticInterpreter> NUMBER_STACK = new Stack<>();

    // 操作符栈
    private Stack<String> OPERATOR_STACK = new Stack<>();

    public Calculator(String expression) {
        this.parse(expression);
    }

    private void parse(String expression) {
        // 默认使用空格进行分割
        String[] elements = expression.split(" ");
        IArithmeticInterpreter left, right;

        for (int i = 0; i < elements.length; i++) {
            String element = elements[i];
            if(OperatorUtil.isLowOperator(element)){
                // 如果是低优先级操作符，则将当前栈中数据全部计算
                while(!OPERATOR_STACK.empty() && OperatorUtil.isOperator(OPERATOR_STACK.peek())){
                    calculate0();
                }
                // 计算结束后，将当前操作符入栈
                OPERATOR_STACK.push(element);
                System.out.println("操作符入栈：" + element);

            }else if(OperatorUtil.isHighOperator(element)){
                // 如果是高优先级操作符，则只有栈的最上面是高优先级时，才会进行运算
                while(!OPERATOR_STACK.empty() && OperatorUtil.isHighOperator(OPERATOR_STACK.peek())){
                    calculate0();
                }
                // 计算结束后，将当前操作符入栈
                OPERATOR_STACK.push(element);
                System.out.println("操作符入栈：" + element);
            }else if(OperatorUtil.isLeftBrackets(element)){
                // 如果是左括号，则不做处理，直接入栈
                OPERATOR_STACK.push(element);
                System.out.println("操作符入栈：" + element);
            }else if(OperatorUtil.isRightBrackets(element)){
                // 如果是右括号，需要从最上面一直往下找，直到找到第一个左括号，进行运算
                while (!"(".equals(OPERATOR_STACK.peek())){
                    calculate0();
                }
                // 清除匹配的左括号
                String operator = OPERATOR_STACK.pop();
                System.out.println("操作符出栈：" + operator);
            }else{
                left = new NumberArithmeticInterpreter(Integer.valueOf(element));
                NUMBER_STACK.push(left);
                System.out.println("数字入栈：" + element);
            }
        }
        //最后当栈中不是空的时候继续运算，知道栈中为空即可
        while (!OPERATOR_STACK.isEmpty()) {
            calculate0();
        }
    }

    private void calculate0(){
        IArithmeticInterpreter right = NUMBER_STACK.pop();
        IArithmeticInterpreter left = NUMBER_STACK.pop();
        String operator = OPERATOR_STACK.pop();
        System.out.println("数字出栈：" + right);
        System.out.println("数字出栈：" + left);
        System.out.println("操作符出栈：" + operator);
        Interpreter interpreter = OperatorUtil.getInterpreter(left, right, operator);
        NUMBER_STACK.push(interpreter);
        System.out.println("结果入栈：" + interpreter.toString());
    }

    public int calculate(){
        return this.NUMBER_STACK.pop().interpret();
    }
}
